package graphicinterface;

import java.util.LinkedList;

import bookworm.BestReviewersRecommendationsRetriever;
import bookworm.Book;
import bookworm.BookCoverAndHowManyDaysToFinishIt;
import bookworm.BooksAndRatingOfOneAuthor;
import bookworm.FiltersReviewsByTag;
import bookworm.GetRecentReviews;
import bookworm.GetReviewerRatingFromAPI;
import bookworm.GetReviewerRatingFromTextFile;
import bookworm.GetReviewersRatingsInterface;
import bookworm.LooksForHowManyDaysToReadBook;
import bookworm.Review;
import bookworm.SearchBestAuthorsBasedOnTag;
import bookworm.SearchBestBooksBasedOnTag;
import bookworm.TestIfUserIsConnected;

/**
 * this class will be the facade which all the system's UI will direct to when
 * they need something functional of the system to be executed. It's the Facade
 * that stays between UI layer and Functional layer
 *
 */
public class SystemFunctionalitiesFacade 
{
	private static SystemFunctionalitiesFacade singletonForFacade;
	private BestReviewersRecommendationsRetriever providesBookRecommendations;
	private LooksForHowManyDaysToReadBook knowsHowLongToReadABook;
	private GetReviewersRatingsInterface getsReviewersRatings;
	
	private SystemFunctionalitiesFacade()
	{
		providesBookRecommendations = new BestReviewersRecommendationsRetriever();
		knowsHowLongToReadABook = new LooksForHowManyDaysToReadBook();
		this.getsReviewersRatings = new GetReviewerRatingFromTextFile();
	}
	
	public synchronized static SystemFunctionalitiesFacade getInstance()
	{
		if(singletonForFacade == null)
		{
			singletonForFacade = new SystemFunctionalitiesFacade();
		}
		
		return singletonForFacade;
	}
	
	public LinkedList<String> getBestReviewersUsername()
	{
		return this.providesBookRecommendations.getBestReviewersUserName();
	}
	
	public LinkedList<String> getTagsTopReviewerLikesToRead(String topReviewerName)
	{
		return this.providesBookRecommendations.getTagsTopReviewerLikesToRead(topReviewerName);
	}
	
	public LinkedList<Review> getBestBookReviewsByTopReviewer(String topReviewerName)
	{
		return this.providesBookRecommendations.getAllTopRatedReviewsFromTopReviewer(topReviewerName);
	}
	
	public LinkedList<Book> getBookRecommendationsByTopReviewer(String topReviewerUserName)
	{
		return this.providesBookRecommendations.getAllBookRecommendationsFromTopReviewer(topReviewerUserName);
	}
	
	public LinkedList<String> findBooksInHistoryWithThisTitle(String bookTitle)
	{
		this.knowsHowLongToReadABook.lookForAllBooksHistoryData();
		return this.knowsHowLongToReadABook.searchForBooksInHistoryWithThisName(bookTitle);
	}
	
	public BookCoverAndHowManyDaysToFinishIt howManyDaysToFinishThisBook(String bookName)
	{
		this.knowsHowLongToReadABook.lookForAllBooksHistoryData();
		return this.knowsHowLongToReadABook.howManydaysToFinishThisBook(bookName);
	}
	
	public LinkedList<Review> filterReviewsByTag(LinkedList<String> tags, LinkedList<Review> allReviews)
	{
		return FiltersReviewsByTag.filterReviewsByTags(tags, allReviews);
	}
	
	public LinkedList<Review> getRecentReviewsByTag(String tag)
	{
		return GetRecentReviews.getRecentReviewsByTag(tag);
	}
	
	public LinkedList<BooksAndRatingOfOneAuthor> getBestAuthorsAndBooksBasedOnTag(String tag)
	{
		SearchBestAuthorsBasedOnTag bestAuthorsFinder = new SearchBestAuthorsBasedOnTag(tag);
		LinkedList<BooksAndRatingOfOneAuthor> bestAuthorsAndBooksBasedOnTag = 
									bestAuthorsFinder.getBestAuthorsBooksAndRatingsBasedOnTag();
		return bestAuthorsAndBooksBasedOnTag;
	}
	
	public LinkedList<Integer> getAllBookReviewersRatings(LinkedList<String> bookReviewersNames)
	{
		LinkedList<Integer> reviewersGrades = new LinkedList<Integer>();
		for(int i = 0; i < bookReviewersNames.size(); i++)
		{
			String singleReviewerName = bookReviewersNames.get(i);
			int reviewerGrade = this.getBookReviewerRating(singleReviewerName);
			reviewersGrades.add(reviewerGrade);
		}
		return reviewersGrades;
	}
	
	public Integer getBookReviewerRating(String bookReviewerName)
	{
		int bookReviewerRating = this.getsReviewersRatings.getReviewerRating(bookReviewerName);
		if(bookReviewerRating != -1)
		{
			return bookReviewerRating;
		}
		else
		{
			//-1 means the book reviewer grade was not found from text file and we need to change strategy to use API
			this.getsReviewersRatings = new GetReviewerRatingFromAPI();
			bookReviewerRating = this.getsReviewersRatings.getReviewerRating(bookReviewerName);
			//let's return this instance to get reviewer's rating by text file which it's the default
			this.getsReviewersRatings = new GetReviewerRatingFromTextFile();
			return bookReviewerRating;
		}
	}
	
	public LinkedList<Book> getBestBooksFromSpecificTag(String tag)
	{
		SearchBestBooksBasedOnTag searchBestBooks = new SearchBestBooksBasedOnTag(tag);
		LinkedList<Book> bestBooksFromTag = searchBestBooks.getBestBooksFromTag();
		return bestBooksFromTag;
	}
	
	public boolean computerIsConnectedToInternet()
	{
		return TestIfUserIsConnected.hasInternetConnection();
	}
	

}
